﻿// -----------------------------------------------------------------------
// <copyright file="SQLPattern.cs" company="Hexacta S.A.">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace SQLVis.Entidades
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using gudusoft.gsqlparser;
    using System.Collections;
    using SQLVis.Entidades;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class SQLPattern
    {
        private int sumatoria_de_tiempo = 0;
        //temporalmente para generar hijos
        Random rnd = new Random(1234);
        public int MinTime { get; set; }
        public int MaxTime { get; set; }
        public double AverageTime { get { return SlowQueries.Count > 0 ? sumatoria_de_tiempo / SlowQueries.Count : 0; } }
        public string PatternName { get; set; }
        public IList<InfoDeLaQuery> SlowQueries { get; set; } //todas las queryes sin subdividir
        public IList<SQLPatternSubGroup> SubPatterns { get {return  diccionario_de_subpatrones.Values.ToList(); } }
        //agrupo por los campos que selecciona
        Dictionary<string, SQLPatternSubGroup> diccionario_de_subpatrones = new Dictionary<string, SQLPatternSubGroup>();
        //subpatrones - luego adaptar para que haya solo una clase y la misma sea recursiva
        //IList<SQLPattern> subpatterns = new List<SQLPattern>();
        //public IList<SQLPattern> SubPatterns
        //{
        //    get { return ConvertToPattern(diccionario_de_subpatrones.Values.ToList()); } 

        //}

        #region Constructores

        public SQLPattern(string patternName, IList<InfoDeLaQuery> queries, IList<SQLPatternSubGroup> subgroups)
        {
            PatternName = patternName;
            SlowQueries = queries;
            MinTime = int.MaxValue;
            MaxTime = 0;
        }

        public SQLPattern()
        {
            MinTime = int.MaxValue;
            MaxTime = 0;
            PatternName = string.Empty;
            SlowQueries = new List<InfoDeLaQuery>();

        }

        public SQLPattern(InfoDeLaQuery q)
        {

            MinTime = int.MaxValue;
            MaxTime = 0;
            sumatoria_de_tiempo = q.QueryTime;
            PatternName = q.PatronAgrupamiento;
            SlowQueries = new List<InfoDeLaQuery>();
            SlowQueries.Add(q);

        }

        #endregion


        public int Count()
        {
            return SlowQueries.Count;

            //IList<SQLPatternSubGroup> subPatterns = diccionario_de_subpatrones.Values.ToList();
            //int res = 0;
            ////calcular la cantidad de slow queries que tienen los subgrupos o subpatterns
            //foreach (SQLPatternSubGroup sp in subPatterns)
            //{
            //    res = res + SlowQueries.Count; //+ sp.Patron.Count();
            //}

            //return res;
        
        }

        //TO DELETE
        private IList<SQLPattern> ConvertToPattern(IList<SQLPatternSubGroup> list)
        {
 	         IList<SQLPattern> res = new List<SQLPattern>();   
             foreach (SQLPatternSubGroup item in list)
	        {
		        //Crear el subpatron
                SQLPattern p = new SQLPattern( item.Patron.AverageTime.ToString(),
                                               item.SlowQueries,
                                               new List<SQLPatternSubGroup>()
                                               );

                res.Add(p);
	        }

             return res;
        }

        public ISet<string> Tablas { get; set; }

       

        
        public virtual void AgregarNuevaQuery(InfoDeLaQuery info)
        {
            CalculosGeneralesYAgregarAlCjto(info);
            AgregarAlSubGrupoCorrespondiente(info);
        }

        private void AgregarAlSubGrupoCorrespondiente(InfoDeLaQuery info)
        {
            string sub_patron_key = ObtenerNombreSubPatron(info);


            SQLPatternSubGroup el_sub_patron;
            if (diccionario_de_subpatrones.ContainsKey(sub_patron_key))
            {
                el_sub_patron = diccionario_de_subpatrones[sub_patron_key];
                el_sub_patron.AgregarNuevaQuery(info);
            }
            else
            {
                el_sub_patron = new SQLPatternSubGroup(this);
                el_sub_patron.AgregarNuevaQuery(info);

                diccionario_de_subpatrones.Add(sub_patron_key, el_sub_patron);
            }
        }

        protected void CalculosGeneralesYAgregarAlCjto(InfoDeLaQuery info)
        {
            sumatoria_de_tiempo += info.QueryTime;

            MinTime = Math.Min(MinTime, info.QueryTime);
            MaxTime = Math.Max(MaxTime, info.QueryTime);

            SlowQueries.Add(info);//al conjunto de todas las queryes
        }

        private string ObtenerNombreSubPatron(InfoDeLaQuery info)
        {
            //la clave para identificar un subpatron va a ser tomar los campos de la query y ordenarlos alfabeticamente y formar un string
            string resultado = string.Empty;

            IList<string> campos_ordenados = ListaOrdenadaDeNombresDeCampos(info);

            for (int i = 0; i < campos_ordenados.Count; i++)
            {
                resultado += campos_ordenados[i] + "#";
            }

            return resultado;
        }

        private IList<string> ListaOrdenadaDeNombresDeCampos(InfoDeLaQuery info)
        {
            IList<string> campos = new List<string>();
            TLzFieldList lista_de_campos;
            lista_de_campos=info.Query.Fields;
            foreach (TLzField field in lista_de_campos)
            {
                campos.Add(field.FieldName);
            }
            string[] campos2 = campos.ToArray();
            Array.Sort(campos2);
            return campos2;
        }


        //Solo para probar
        public SQLPattern GenerarSQLPattern()
        {
            SlowQueries = new List<InfoDeLaQuery>();
            int sixe = rnd.Next(3, 50);
            for (int i = 0; i < sixe; i++)
            {
                InfoDeLaQuery q = new InfoDeLaQuery();
                q.QueryTime = rnd.Next(1,10);
                sumatoria_de_tiempo = sumatoria_de_tiempo + q.QueryTime;
                q.RowsExamined = rnd.Next(3, 4000);
                SlowQueries.Add(q);
            }
            
            return this;
        }

        public override string ToString()
        {
            //return "Tiempo: " + this.AverageTime.ToString() + System.Environment.NewLine +
            //       "Consulta: " + SlowQueries[0].toStringSeparadoEnLineas();
            if (SlowQueries.Count > 0)
                return SlowQueries[0].ToString();
            else
                return string.Empty;
        }
    }
}

